#include "led_control.h"
#include <LNM8F01.h>
#include "key_contorl.h"
#include "system_init.h"

#define LED_STRIP_MAX_LEN 150

// 根据官方文档在24MHz下重新计算的WS2812时序参数
// T0H = (9+1)/24M = 0.417us
// T0L = (19+1)/24M = 0.833us
// T1H = (19+1)/24M = 0.833us (由T0LNUM决定)
// T1L = (9+1)/24M = 0.417us (由T0HNUM决定)
#define LED_T0H_VAL 9
#define LED_T0L_VAL 19

//==================== 底层LED驱动相关 ====================

static void led_hw_init(void)
{
    PAHSEL |= 0x1<<1;   // LED0  PA4
    PAHSEL |= 0x1<<6;   // LED1  PA7

    // 配置时序以适应24MHz系统时钟
    LED0T0H = LED_T0H_VAL;
    LED0T0L = LED_T0L_VAL;
    // 根据新文档，不存在T1H/T1L寄存器，故删除

    LED1T0H = LED_T0H_VAL;
    LED1T0L = LED_T0L_VAL;
    // 根据新文档，不存在T1H/T1L寄存器，故删除
}

static void flush_led_strips(void);

//==================== 高层参数与模式控制 ====================

static uint32_t ledAnimTimer_s = 0;
static led_color_t ledFrameBuffer_s[LED_STRIP_MAX_LEN];
static led_strip_param_t ledParam = {10, SPEED_LEVEL_1, MODE_ALWAYS_ON, 1};
static uint8_t lastQuantity_s = 0;

static const led_color_t colorTable[10] = {
    {255, 255, 255}, {255, 0, 0}, {0, 255, 0}, {0, 0, 255}, {255, 255, 0},
    {0, 255, 255}, {255, 0, 255}, {128, 0, 0}, {0, 128, 0}, {0, 0, 128}
};

static uint8_t blink_on_s = 1;
static uint32_t blink_timer_s = 0;
static uint8_t breath_val_s = 0;
static uint8_t breath_dir_s = 1;
static uint32_t breath_timer_s = 0;
static uint8_t flow_pos_s = 0;
static uint32_t flow_timer_s = 0;
static uint8_t meteor_pos_s = 0;
static uint32_t meteor_timer_s = 0;

// 新模式的状态变量
static uint8_t welcome_pos_s = 0;
static uint32_t welcome_timer_s = 0;
static uint8_t brake_on_s = 1;
static uint32_t brake_timer_s = 0;
static uint16_t rainbow_hue_s = 0;
static uint32_t rainbow_timer_s = 0;

// 新增：为每个模式定义非线性的速度查找表（单位：毫秒，数值越小速度越快）
// 1档最慢, 5档最快
static const uint8_t breath_speed_s[5] = {8, 6, 4, 2, 1}; 
static const uint8_t flow_speed_s[5] = {50, 35, 20, 10, 5};
static const uint8_t meteor_speed_s[5] = {40, 25, 15, 8, 3};
static const uint8_t welcome_speed_s[5] = {40, 25, 15, 8, 3};
static const uint8_t rainbow_speed_s[5] = {30, 20, 10, 5, 2};

// 彩虹模式辅助函数
static led_color_t color_wheel(uint8_t wheelPos) {
    led_color_t color;
    wheelPos = 255 - wheelPos;
    if(wheelPos < 85) {
        color.red = 255 - wheelPos * 3;
        color.green = 0;
        color.blue = wheelPos * 3;
    } else if(wheelPos < 170) {
        wheelPos -= 85;
        color.red = 0;
        color.green = wheelPos * 3;
        color.blue = 255 - wheelPos * 3;
    } else {
        wheelPos -= 170;
        color.red = wheelPos * 3;
        color.green = 255 - wheelPos * 3;
        color.blue = 0;
    }
    return color;
}

// 各模式渲染子函数声明
static void led_mode_always_on(uint8_t current_quantity, led_color_t color);
static void led_mode_blink(uint8_t current_quantity, led_color_t color);
static void led_mode_breath(uint8_t current_quantity, led_color_t color);
static void led_mode_flow(uint8_t current_quantity, led_color_t color);
static void led_mode_meteor(uint8_t current_quantity, led_color_t color);
static void led_mode_welcome(uint8_t current_quantity, led_color_t color);
static void led_mode_rainbow(uint8_t current_quantity);

static void calculate_led_frame(void)
{
    uint8_t i = 0, max_len = 0;
    led_color_t color = {0,0,0};
    uint32_t now = get_system_time();
    uint8_t current_quantity = ledParam.quantity;
    if (current_quantity == 0 && lastQuantity_s == 0) return;
    color = colorTable[(ledParam.colorIndex-1) % 10];

    // 状态更新部分（保留原有）
    switch(ledParam.mode) {
    case MODE_BLINK:
        if(now - blink_timer_s > (300 - ledParam.speed*50)) { blink_on_s = !blink_on_s; blink_timer_s = now; }
        break;
    case MODE_BREATH:
        if(now - breath_timer_s > breath_speed_s[ledParam.speed-1]) {
            breath_timer_s = now;
            if(breath_dir_s) { if(breath_val_s < 255) breath_val_s++; else breath_dir_s = 0; } 
            else { if(breath_val_s > 0) breath_val_s--; else breath_dir_s = 1; }
        }
        break;
    case MODE_FLOW:
        if(now - flow_timer_s > flow_speed_s[ledParam.speed-1]) {
            flow_timer_s = now; flow_pos_s = (flow_pos_s+1) % current_quantity; 
        }
        break;
    case MODE_METEOR:
        if(now - meteor_timer_s > meteor_speed_s[ledParam.speed-1]) {
            meteor_timer_s = now; meteor_pos_s = (meteor_pos_s+1) % current_quantity; 
        }
        break;
    case MODE_WELCOME:
        if(now - welcome_timer_s > welcome_speed_s[ledParam.speed-1]) {
            welcome_timer_s = now;
            if (welcome_pos_s < (current_quantity / 2) + 1) { welcome_pos_s++; } else { welcome_pos_s = 0; }
        }
        break;
    case MODE_RAINBOW:
        if(now - rainbow_timer_s > rainbow_speed_s[ledParam.speed-1]) {
            rainbow_timer_s = now; rainbow_hue_s++;
        }
        break;
    default: break;
    }

    max_len = (current_quantity > lastQuantity_s) ? current_quantity : lastQuantity_s;

    // 分发到各模式渲染函数
    switch(ledParam.mode) {
    case MODE_ALWAYS_ON:
        led_mode_always_on(current_quantity, color); break;
    case MODE_BLINK:
        led_mode_blink(current_quantity, color); break;
    case MODE_BREATH:
        led_mode_breath(current_quantity, color); break;
    case MODE_FLOW:
        led_mode_flow(current_quantity, color); break;
    case MODE_METEOR:
        led_mode_meteor(current_quantity, color); break;
    case MODE_WELCOME:
        led_mode_welcome(current_quantity, color); break;
    case MODE_RAINBOW:
        led_mode_rainbow(current_quantity); break;
    default:
        led_mode_always_on(current_quantity, color); break;
    }
    // 清零多余LED
    for(i = current_quantity; i < max_len; i++) {
        ledFrameBuffer_s[i].red = 0;
        ledFrameBuffer_s[i].green = 0;
        ledFrameBuffer_s[i].blue = 0;
    }
}

// 各模式渲染子函数实现
static void led_mode_always_on(uint8_t current_quantity, led_color_t color) {
    uint8_t i;
    for(i=0; i<current_quantity; i++) { ledFrameBuffer_s[i] = color; }
}
static void led_mode_blink(uint8_t current_quantity, led_color_t color) {
    uint8_t i;
    if(blink_on_s) { for(i=0; i<current_quantity; i++) { ledFrameBuffer_s[i] = color; } } 
    else { for(i=0; i<current_quantity; i++) { ledFrameBuffer_s[i].red = 0; ledFrameBuffer_s[i].green = 0; ledFrameBuffer_s[i].blue = 0; } }
}
static void led_mode_breath(uint8_t current_quantity, led_color_t color) {
    uint8_t i;
    for(i=0; i<current_quantity; i++) {
        ledFrameBuffer_s[i].red = (color.red * breath_val_s) / 255;
        ledFrameBuffer_s[i].green = (color.green * breath_val_s) / 255;
        ledFrameBuffer_s[i].blue = (color.blue * breath_val_s) / 255;
    }
}
static void led_mode_flow(uint8_t current_quantity, led_color_t color) {
    uint8_t i;
    for(i=0; i<current_quantity; i++) {
        if(i==flow_pos_s) { ledFrameBuffer_s[i] = color; } 
        else { ledFrameBuffer_s[i].red = 0; ledFrameBuffer_s[i].green = 0; ledFrameBuffer_s[i].blue = 0; }
    }
}
static void led_mode_meteor(uint8_t current_quantity, led_color_t color) {
    uint8_t i;
    for(i=0; i<current_quantity; i++) {
        uint8_t fade = 0;
        if(i == meteor_pos_s) fade = 255;
        else if((meteor_pos_s > 0 && i == meteor_pos_s - 1) || (meteor_pos_s == 0 && i == current_quantity -1)) fade = 128;
        else if((meteor_pos_s > 1 && i == meteor_pos_s - 2) || (meteor_pos_s <= 1 && i >= current_quantity - (2 - meteor_pos_s))) fade = 64;
        else fade = 0;
        ledFrameBuffer_s[i].red = (color.red * fade) / 255;
        ledFrameBuffer_s[i].green = (color.green * fade) / 255;
        ledFrameBuffer_s[i].blue = (color.blue * fade) / 255;
    }
}
static void led_mode_welcome(uint8_t current_quantity, led_color_t color) {
    uint8_t i;
    for(i=0; i < current_quantity; i++) {
        ledFrameBuffer_s[i].red = 0; ledFrameBuffer_s[i].green = 0; ledFrameBuffer_s[i].blue = 0;
    }
    for(i=0; i < welcome_pos_s; i++) {
        uint8_t center = current_quantity / 2;
        if (center + i < current_quantity) {
            ledFrameBuffer_s[center + i] = color;
        }
        if (center - i >= 0) {
            ledFrameBuffer_s[center - i] = color;
        }
    }
}
static void led_mode_rainbow(uint8_t current_quantity) {
    uint8_t i;
    for(i=0; i<current_quantity; i++) {
        ledFrameBuffer_s[i] = color_wheel((i * 256 / current_quantity + rainbow_hue_s) & 255);
    }
}

void init_led_control(void)
{
    uint8_t i;
    led_hw_init();
    sync_led_param_from_key();
    lastQuantity_s = ledParam.quantity;
    for(i = 0; i < LED_STRIP_MAX_LEN; i++)
    {
        ledFrameBuffer_s[i].red = 0;
        ledFrameBuffer_s[i].green = 0;
        ledFrameBuffer_s[i].blue = 0;
    }
}

void update_led_control(void)
{
    uint32_t now = get_system_time();

    if (now - ledAnimTimer_s >= 20) 
    {
        ledAnimTimer_s = now;
        sync_led_param_from_key();
        calculate_led_frame();
        flush_led_strips();
    }
}

static void flush_led_strips(void)
{
    uint16_t i;
    uint8_t send_len = (ledParam.quantity > lastQuantity_s) ? ledParam.quantity : lastQuantity_s;
    
    if (send_len == 0) {
        lastQuantity_s = 0;
        return;
    }

    EA = 0; // 进入临界区，关闭总中断

    // --- 发送 LED 0 ---
    LEDCTR |= (1 << 0);
    for (i = 0; i < send_len; i++)
    {
        while(LEDSTAT & (1<<0)); LED0DATA = ledFrameBuffer_s[i].green;
        while(LEDSTAT & (1<<0)); LED0DATA = ledFrameBuffer_s[i].red;
        while(LEDSTAT & (1<<0)); LED0DATA = ledFrameBuffer_s[i].blue;
        
        if (i == send_len - 1) {
            // 在写入最后一个字节后，立即设置帧结束标志
            LEDCTR |= (1 << 1);
        }
    }
    while(!(LEDSTAT & (1<<4)));
    LEDCTR &= ~(1 << 0);
    LEDICLR |= (1 << 0);

    // --- 发送 LED 1 ---
    LEDCTR |= (1 << 2);
    for (i = 0; i < send_len; i++)
    {
        while(LEDSTAT & (1<<2)); LED1DATA = ledFrameBuffer_s[i].green;
        while(LEDSTAT & (1<<2)); LED1DATA = ledFrameBuffer_s[i].red;
        while(LEDSTAT & (1<<2)); LED1DATA = ledFrameBuffer_s[i].blue;
        
        if (i == send_len - 1) {
            // 在写入最后一个字节后，立即设置帧结束标志
            LEDCTR |= (1 << 3);
        }
    }
    while(!(LEDSTAT & (1<<5)));
    LEDCTR &= ~(1 << 2);
    LEDICLR |= (1 << 1);
    
    EA = 1; // 退出临界区，打开总中断

    lastQuantity_s = ledParam.quantity;
}


void set_led_strip_param(led_strip_enumType_t strip, const led_strip_param_t *paramPtr)
{
    if(paramPtr == 0) return;
    ledParam = *paramPtr;
}

void get_led_strip_param(led_strip_enumType_t strip, led_strip_param_t *paramPtr)
{
    if(paramPtr == 0) return;
    *paramPtr = ledParam;
}

void set_led_strip_color(led_strip_enumType_t strip, led_color_t color)
{
    uint8_t i;
    for(i = 0; i < ledParam.quantity; i++) { ledFrameBuffer_s[i] = color; }
    for(i = ledParam.quantity; i < lastQuantity_s; i++) { ledFrameBuffer_s[i].red = 0; ledFrameBuffer_s[i].green = 0; ledFrameBuffer_s[i].blue = 0; }
    flush_led_strips();
}

void sync_led_param_from_key(void)
{
    ledParam.quantity = get_key_quantity();
    ledParam.speed    = get_key_speed();
    ledParam.mode     = get_key_mode();
    ledParam.colorIndex = get_key_color();
}
